package com.supinfo.suptracking.dao.jpa;

import com.supinfo.suptracking.dao.ZoneDao;
import com.supinfo.suptracking.entity.Car;
import com.supinfo.suptracking.entity.Zone;
import com.supinfo.suptracking.entity.Zone_;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

/**
 *
 * @author Fabien, Jérémy, Ludovic, Brice
 */

@Stateless
public class JpaZoneDao implements ZoneDao{

    @PersistenceContext
    private EntityManager em;
    
    @Override
    public void addZone(Zone zone) {
        em.persist(zone);
    }
    
    @Override
    public List<Zone> getZoneByPosition(String latitude, String longitude) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Zone> query = cb.createQuery(Zone.class);
        Root<Zone> zone = query.from(Zone.class);
        
        List<Predicate> predicates = new ArrayList<>();
        predicates.add(cb.equal(zone.get(Zone_.latitude), latitude));
        
        query.where(predicates.toArray(new Predicate[predicates.size()]));
        
        List<Zone> listZoneLatitude = em.createQuery(query).getResultList();
        List<Zone> listZones = null;
        // Get the list of zones by latitude, and search for the zones with
        // the longitude given
        for(Zone zoneLat : listZoneLatitude)
        {
            String longit = zoneLat.getLongitude();
            if(longit.equalsIgnoreCase(longitude))
            {
                listZones.add(zoneLat);
            }
        }
        return listZones;
    }

    @Override
    public List<Zone> getAllZoneByCar(Car car) {
        Long carId = car.getId();
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Zone> query = cb.createQuery(Zone.class);
        
        Root<Zone> zone = query.from(Zone.class);
        List<Predicate> predicates = new ArrayList<>();
        
        predicates.add(cb.equal(zone.get(Zone_.carId), carId));
        query.where(predicates.toArray(new Predicate[predicates.size()]));
        
        return em.createQuery(query).getResultList();
    }

    @Override
    public List<Zone> getAllZone() {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Zone> query = cb.createQuery(Zone.class);
        return em.createQuery(query).getResultList();
    }

    @Override
    public List<Zone> getAllZonebyRadiusMeter(Long radiusMeter) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Zone> query = cb.createQuery(Zone.class);
        Root<Zone> zone = query.from(Zone.class);
        
        List<Predicate> predicates = new ArrayList<>();
        predicates.add(cb.equal(zone.get(Zone_.radiusMeter), radiusMeter));
        
        query.where(predicates.toArray(new Predicate[predicates.size()]));
        return em.createQuery(query).getResultList();
    }

    @Override
    public List<Zone> getAllZoneByTimeStamp(Date lowTimestamp, Date highTimeStamp) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Zone> query = cb.createQuery(Zone.class);
        Root<Zone> zone = query.from(Zone.class);
        
        List<Predicate> predicates = new ArrayList<>();
        predicates.add(cb.equal(zone.get(Zone_.lowTimeStamp), lowTimestamp));
        
        query.where(predicates.toArray(new Predicate[predicates.size()]));
        
        List<Zone> listZoneLowTS = em.createQuery(query).getResultList();
        List<Zone> listZones = null;
        // Get the list of zones by latitude, and search for the zones with
        // the longitude given
        for(Zone zoneLowTS : listZoneLowTS)
        {
            Date highTS = zoneLowTS.getHighTimestamp();
            if(highTS == highTimeStamp)
            {
                listZones.add(zoneLowTS);
            }
        }
        return listZones;        
    }
    
    @Override 
    public Zone getZoneById(Long id) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Zone> query = cb.createQuery(Zone.class);
        Root<Zone> invoice = query.from(Zone.class);
        
        List<Predicate> predicates = new ArrayList<>();
        predicates.add(cb.equal(invoice.get(Zone_.id), id));
        
        query.where(predicates.toArray(new Predicate[predicates.size()]));
        
        if (!em.createQuery(query).getResultList().isEmpty())
        {
            return em.createQuery(query).getResultList().get(0);
        }
        else
        {
            Zone zone = null;
            return zone;
        }
    }
    
    @Override
    public void updateZone(Zone zone) {
        em.merge(zone);
    }
    
    @Override
    public void delZone(Zone zone) { 
        em.remove(em.merge(zone));
    }
}
